package jp.seraph.jsade.sexpression;

import java.text.ParseException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jp.seraph.jsade.message.MessageUtil;

public class LRParser extends AbstractParser implements ExpressionParser {
    public LRParser(){
    }

    @SuppressWarnings("unchecked")
    public List<SExpression> parse(String aExpression) throws ParseException{
        mExpression = aExpression;
        try{
        if(this.yyparse() == 0)
            return (List<SExpression>)super.getYYVAL();
        else
            throw new ParseException(MessageUtil.parseException(), -1);
        }catch(Error e){
            throw new ParseException(e.getMessage(), -1);
        }
    }

    private String mExpression;
    private final Pattern ATOM_PATTERN = Pattern.compile("^[^\\s()]+");

    /**
     *
     * @see jp.seraph.jsade.sexpression.AbstractParser#yyerror(java.lang.String)
     */

    protected void yyerror(String aMsg) {
        throw new Error(aMsg);
    }

    /**
     *
     * @see jp.seraph.jsade.sexpression.AbstractParser#yylex()
     */

    protected int yylex() {
        mExpression = mExpression.trim();

        if(mExpression.length() == 0)
            return 0;

        if(mExpression.charAt(0) == '('){
            mExpression = mExpression.substring(1);
            return '(';
        }

        if(mExpression.charAt(0) == ')'){
            mExpression = mExpression.substring(1);
            return ')';
        }

        Matcher tAtomMatcher = ATOM_PATTERN.matcher(mExpression);
        if(tAtomMatcher.find()){
            mExpression = tAtomMatcher.replaceFirst("");
            super.setYYLVAL(tAtomMatcher.group());
            return AbstractParser.ATOM;
        }

        throw new Error(MessageUtil.lexException(mExpression.charAt(0)));
    }
}
